package com.tenebrous.jestic.chain;

import com.rain.ops.sdk.dto.ApiResult;
import com.tenebrous.jestic.auth.AuthTokenGenerator;
import com.tenebrous.jestic.context.JesticContext;
import com.tenebrous.jestic.context.JesticTask;
import com.tenebrous.jestic.context.Response;
import com.tenebrous.jestic.entity.model.request.JesticAuthorityRequest;
import com.tenebrous.jestic.entity.model.response.JesticAuthorityResponse;
import com.tenebrous.jestic.entity.server.JesticServer;
import com.tenebrous.jestic.enums.InstanceStatusEnum;
import com.tenebrous.jestic.server.AbstractInstanceContext;
import com.tenebrous.jestic.server.Instance;
import com.tenebrous.jestic.server.ServerInstance;
import com.tenebrous.jestic.service.server.AuthServerService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * @Description:
 * @Project: jestic-spring-boot
 * @Package: com.zy.tenebrous.jestic.chain
 * @Author: zhangya
 * @CreateTime: 2023-06-28  18:15
 * @Version: 1.0.0
 */
@Slf4j
@Service("JesticAuthHandler")
public class JesticAuthHandler extends AbstractJesticChainHandler<JesticAuthorityRequest, JesticAuthorityResponse> {

    @Resource
    private final AuthServerService authServerService;

    @Resource
    private final AbstractInstanceContext abstractInstanceContext;

    @Resource
    private final AuthTokenGenerator authToken;

    public JesticAuthHandler(AuthServerService authServerService, AbstractInstanceContext abstractInstanceContext, AuthTokenGenerator authToken){
        this.authServerService = authServerService;
        this.abstractInstanceContext = abstractInstanceContext;
        this.authToken = authToken;
    }
    private int order;

    @Override
    public void handler(JesticContext<? extends JesticTask, ? extends Response> context) {
        JesticAuthorityRequest request = (JesticAuthorityRequest) context.getRequest();
        log.info("JesticAuthHandler.handler.request[{}]", request);
        JesticAuthorityResponse response = (JesticAuthorityResponse) context.getResponse();
        JesticServer jesticServer = authServerService.selectServer(request.getServerId(), request.getServerName());
        if (Objects.isNull(jesticServer)) {
            log.info("jestic [ServerServiceGrpcImpl.authority] client [{}] server not found", request.getServerName());
            response.setCode(500);
            response.setMessage("server not found");
        } else if (jesticServer.getServerStatus() != 1) {
            log.info("jestic [ServerServiceGrpcImpl.authority] client [{}] status  not abnormal", request.getServerName());
            response.setCode(500);
            response.setMessage("server status not is running");
        } else {
            Instance instance = new ServerInstance(abstractInstanceContext.initContext(jesticServer, authToken)).initInstance();
            log.info("jestic [ServerServiceGrpcImpl.authority] client [{}] init instance:[{}]", request.getServerName(), instance.getInstanceId());
            // 设置客户端信息
            instance.setIp(request.getIp());
            instance.setPort(request.getPort());
            instance.setGrpcPort(request.getGrpcPort());
            instance.setInstanceStatus(InstanceStatusEnum.HEALTHY);
            abstractInstanceContext.flushInstance(instance);
            // 给与响应

            response.setId(request.getServerId());
            response.setInstanceId(instance.getInstanceId());
            response.setInstanceStatus(instance.getInstanceStatus().getCode());
            response.setToken(instance.getToken());
            response.setExpire(instance.getExpireTime());
            response.setIsAuth(true);

            response.setCode(200);
            response.setMessage("success");
        }
        if (null != nextHandler) {
            nextHandler.handler(context);
        }
    }

    @Override
    public int order(String taskType) {
        return this.order;
    }

    @Override
    public int getOrder() {
        return order;
    }

    @Override
    public AbstractJesticChainHandler<JesticAuthorityRequest, JesticAuthorityResponse> setOrder(int order) {
        this.order = order;
        return this;
    }

}
